﻿
using System.Collections.Generic;
using Geotools.Geometries;
using System;

namespace AzukiMap.MapSource
{
    //public class GsiSource : MapSource
    public class GsiSource : TileSource
    {
        const int GSI_SOURCE_SRID = 4326;
        const string GSI_DEFAULT_NAME = "Denshi Kokudo";
        const int GSI_DEFAULT_TILEWIDTH = 300;
        const int GSI_TILE_DPI = 96;
        const double WEB_MERC_CIRCLE = 20037508.34 * 2;
        const string GSI_SOURCE_LOGO = "http://cyberjapan.jp/image/logo.gif";

        Dictionary<double, string> _baseUris;
        List<double> _scales;
        Dictionary<double, int> _tileWidth;
        Dictionary<double, double> _geoScales;
        Dictionary<double, double> _tileScalesRev;

        public Dictionary<double, string> BaseUris
        {
            get { return _baseUris; }
            set { _baseUris = value; }
        }

        public List<double> Scales
        {
            get { return _scales; }
            set { _scales = value; }
        }

        public Dictionary<double, int> TileWidth
        {
            get { return _tileWidth; }
            set { _tileWidth = value; }
        }

        public Dictionary<double, double> GeoScales
        {
            get { return _geoScales; }
            set { _geoScales = value; }
        }

        public Dictionary<double, double> TileScalesRev
        {
            get { return _tileScalesRev; }
            set { _tileScalesRev = value; }
        }

        public GsiSource()
            : base(GSI_DEFAULT_NAME, GSI_SOURCE_SRID, CoordinationUnits.DEGREES)
        {
            Init();
        }

        public GsiSource(string name)
            : base(name, GSI_SOURCE_SRID, CoordinationUnits.DEGREES)
        {
            Init();
        }

        void Init()
        {
            _baseUris = new Dictionary<double, string>();
            _scales = new List<double>();
            _tileWidth = new Dictionary<double, int>();
            _geoScales = new Dictionary<double, double>();
            _tileScalesRev = new Dictionary<double, double>();
            SetScaleAndUri();
            SetMaxExtent();
            SetSourceLogo();
        }

        void SetScaleAndUri()
        {
            _baseUris = new Dictionary<double, string>();
            _scales = new List<double>();
            //SetScaleAndUriCore(7.5, 300, "http://cyberjapandata.gsi.go.jp/data/7.5dm/new");
            SetScaleAndUriCore(15, 300, "http://cyberjapandata.gsi.go.jp/data/15/new/");
            SetScaleAndUriCore(30, 300, "http://cyberjapandata.gsi.go.jp/data/30/new/");
            SetScaleAndUriCore(60, 300, "http://cyberjapandata.gsi.go.jp/data/60/new/");
            SetScaleAndUriCore(120, 300, "http://cyberjapandata.gsi.go.jp/data/120/new/");
            SetScaleAndUriCore(240, 300, "http://cyberjapandata.gsi.go.jp/data/240/new/");
            SetScaleAndUriCore(480, 300, "http://cyberjapandata.gsi.go.jp/data/480/new/");
            SetScaleAndUriCore(960, 300, "http://cyberjapandata.gsi.go.jp/data/960/new/");
            SetScaleAndUriCore(1920, 300, "http://cyberjapandata.gsi.go.jp/data/1920/new/");
            SetScaleAndUriCore(3840, 300, "http://cyberjapandata.gsi.go.jp/data/3840/new/");
            SetScaleAndUriCore(7680, 300, "http://cyberjapandata.gsi.go.jp/data/7680/new/");
            SetScaleAndUriCore(15360, 300, "http://cyberjapandata.gsi.go.jp/data/15360/new/");
            SetScaleAndUriCore(30720, 300, "http://cyberjapandata.gsi.go.jp/data/30720/new/");
        }

        void SetScaleAndUriCore(double tileWidthSec, int tileWidthPix, string baseUri)
        {
            double screenScale = GetScreenScale(tileWidthSec, tileWidthPix);
            _baseUris.Add(tileWidthSec, baseUri);
            _scales.Add(screenScale);
            _geoScales.Add(tileWidthSec, screenScale);
            _tileScalesRev.Add(screenScale, tileWidthSec);
            _tileWidth.Add(tileWidthSec, tileWidthPix);
        }

        void SetMaxExtent()
        {
            GTEnvelope maxExtent = new GTEnvelope(121, 154, 20, 47);
            _maxExtent = maxExtent;
        }

        double GetScreenScale(double tileWidthSec, double tileWidthPix)
        {
            var inchesPerMeter = AzukiMapSettings.InchesPerUnit(CoordinationUnits.METERS);
            var meterPerDot = 1.0 / (inchesPerMeter * GSI_TILE_DPI);
            var widthByMeter = WEB_MERC_CIRCLE * (tileWidthSec / 360 * 3600);
            var scale = widthByMeter / tileWidthPix * meterPerDot;
            return scale;
        }

        void SetSourceLogo()
        {
            _sourceLogo = new Uri(GSI_SOURCE_LOGO);
        }
    }
}
